package com.gitee.kenewstar.migration.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.entity.Menu;
import com.gitee.kenewstar.migration.entity.MenuPermission;
import com.gitee.kenewstar.migration.entity.MenuTl;
import com.gitee.kenewstar.migration.function.MenuFunction;
import com.gitee.kenewstar.migration.mapper.MenuMapper;
import com.gitee.kenewstar.migration.mapper.MenuPermissionMapper;
import com.gitee.kenewstar.migration.mapper.MenuTlMapper;
import com.gitee.kenewstar.migration.service.MenuService;
import com.gitee.kenewstar.migration.util.Util;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MenuServiceImpl implements MenuService {

    private final MenuMapper menuMapper;
    private final MenuTlMapper menuTlMapper;
    private final MenuPermissionMapper menuPermissionMapper;


    @Override
    @DS(Const.DEV)
    public List<Menu> devSelectMenuByIds(List<Long> menuIds) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", menuIds);
        return this.menuMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<Menu> devSelectMenuList(List<Menu> list, String fdLevel) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(MenuFunction.FD_LEVEL, fdLevel);
        queryWrapper.in("h_tenant_id", list.stream().map(Menu::getHTenantId).collect(Collectors.toSet()));
        queryWrapper.in("code", list.stream().map(Menu::getCode).collect(Collectors.toSet()));
        List<Menu> menuList = this.menuMapper.selectList(queryWrapper);
        Map<String, String> map = list.stream().collect(Collectors.toMap(x -> x.getCode() + "-" + x.getHTenantId(), Menu::getCode));
        menuList = menuList.stream().filter(x -> Objects.nonNull(map.get(x.getCode() + "-" + x.getHTenantId()))).collect(Collectors.toList());
        menuList.forEach(x -> x.setRootFlag(true));
        // 首次获取复核条件的菜单，然后进行递归循环获取子菜单以及权限集
        List<Menu> menus = this.getMenuList(menuList.stream().map(Menu::getId).collect(Collectors.toList()));
        while (CollUtil.isNotEmpty(menus)) {
            menus.forEach(x -> x.setRootFlag(false));
            menuList.addAll(menus);
            menus = this.getMenuList(menus.stream().map(Menu::getId).collect(Collectors.toList()));
        }
        return menuList;
    }

    private List<Menu> getMenuList(List<Long> parentIds) {
        if (CollUtil.isEmpty(parentIds)) {
            return Collections.emptyList();
        }
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("parent_id", parentIds);
        return this.menuMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<MenuTl> devSelectMenuTl(List<Long> menuIds) {
        if (CollUtil.isEmpty(menuIds)) {
            return Collections.emptyList();
        }
        QueryWrapper<MenuTl> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", menuIds);
        return this.menuTlMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<MenuPermission> devSelectMenuPermission(List<Long> menuIds) {
        if (CollUtil.isEmpty(menuIds)) {
            return Collections.emptyList();
        }
        QueryWrapper<MenuPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("menu_id", menuIds);
        return this.menuPermissionMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.UAT)
    public Map<Long, Long> queryMenuMap(List<Menu> list) {
        Map<Long, Long> map = new HashMap<>(list.size());
        list.forEach(x -> {
            Menu menu = this.queryMenu(x);
            Assert.notNull(menu, "目标环境菜单不存在");
            map.put(x.getId(), menu.getId());
        });
        return map;
    }

    private Menu queryMenu(Menu menu) {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", menu.getCode())
                .eq("h_tenant_id", menu.getHTenantId())
                .eq(MenuFunction.FD_LEVEL, menu.getFdLevel());
        return this.menuMapper.selectOne(queryWrapper);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertMenu(List<Menu> list) {
        list.forEach(x -> x.setHTenantId(Util.getTenant(x.getHTenantId())));
        list.forEach(this.menuMapper::insert);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertMenuTl(List<MenuTl> list) {
        list.forEach(x -> x.setHTenantId(Util.getTenant(x.getHTenantId())));
        list.forEach(this.menuTlMapper::insert);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertMenuPermission(List<MenuPermission> list) {
        list.forEach(x -> x.setTenantId(Util.getTenant(x.getTenantId())));
        list.forEach(this.menuPermissionMapper::insert);
    }
}
